
#ifndef  TEST_CALLBACK_CALLBACK_H
#define  TEST_CALLBACK_CALLBACK_H

#include <functional>
#include "helper/unittest/Tracer.h"

namespace test {
namespace callback {

//template<typename FunctionType>
//struct result_type_from ;
//
//template<typename ResultType, typename... Args>
//struct result_type_from<ResultType(Args...)>{
//    using result_type = ResultType;
//};
//
//
//template<int index, class FunctionType>
//struct arg_type_at;
//
//template<typename ResultType, typename FirstArgType, typename... ArgsType>
//struct arg_type_at<0, ResultType(FirstArgType, ArgsType...)>{
//    using arg_type = FirstArgType;
//};
//
//template<int index, typename ResultType, typename FirstArgType, typename... ArgsType>
//struct arg_type_at<index, ResultType(FirstArgType, ArgsType...)>{
//    using arg_type = typename arg_type_at<index - 1, ResultType(ArgsType...)>::arg_type;
//};
//

template<typename FunctionType>
class CallbackUse {
public:
    using ResultType = typename std::function<FunctionType>::result_type;
    CallbackUse()
    {
    }
    template<typename FP>
    CallbackUse(const FP & fp)
    :cb(fp)
    {
    }
    CallbackUse(const CallbackUse & right)
    :cb(right.cb)
    {
    }
    virtual ~CallbackUse(){}

    template<typename Fp>
    void set(const Fp & cb){
        this->cb = cb;
    }
    const std::function<FunctionType> & get() {
        return cb;
    }
    virtual ResultType call() const {
        return cb();
    }
    virtual ResultType call() {
        return cb();
    }
private:
    std::function<FunctionType> cb;
};



void cbDisconnect(){
    TRACER.operation("cbDisconnect");
}
struct OnDisconnect{
    void operator()(){
        TRACER.operation("cbDisconnect");
    }
};
class Client{
public:
    Client():disconnected(nullptr){
    }
    ~Client(){}

    template<typename Func>
    void setDisconnectCallback(const Func & disconnected){
        TRACER.operation("setDisconnectCallback");
        this->disconnected = disconnected;
    }
    void disconnect(){
        TRACER.operation("disconnect");
        if(disconnected){
            this->disconnected();
        }
    }
private:
   std::function<void ()> disconnected; 
};
} //end of namespace callback
} //end of namespace test

#endif   /* TEST_CALLBACK_CALLBACK_H */
